using System;
using System.IO;
using System.Reflection;
using AutoBuild.Core;
using AutoBuild.Core.Framework;
using Machine.Specifications;
using Rhino.Mocks;

namespace AutoBuild.Specs.Core
{
    [Subject(typeof(RunnerSelector))]
    public class finds_correct_runner : RunnerSelectorSpec
    {
        Because of = () =>
            SelectedRunner = Subject.GetRunner("X");
        
        It should_return_correct_runner = () =>
            SelectedRunner.ShouldEqual(Runner1);
    }

    [Subject(typeof(RunnerSelector))]
    public class returns_null_if_runner_is_not_found : RunnerSelectorSpec
    {
        Because of = () =>
            SelectedRunner = Subject.GetRunner("A");

        It should_return_correct_runner = () =>
            SelectedRunner.ShouldBeNull();
    }

    [Subject(typeof(RunnerSelector))]
    public class throws_exception_on_null_argument : RunnerSelectorSpec
    {
        static Exception Exception;

        Because of = () =>
            Exception = Catch.Exception(() => Subject.GetRunner(null));

        It should_throw_ArgumentException = () =>
            Exception.ShouldBe(typeof (ArgumentException));
    }

    [Subject(typeof(RunnerSelector))]
    public class returns_all_runners : RunnerSelectorSpec
    {
        static IBuildRunner[] _runners;

        Because of = () =>
            _runners = Subject.GetAvailableRunners();

        It should_return_all_runners = () =>
            _runners.ShouldContainOnly(new[] {Runner1, Runner2});
    }

    public abstract class RunnerSelectorSpec : Specification<RunnerSelector>
    {

        protected static IBuildRunner Runner1 = Mock<IBuildRunner>();
        protected static IBuildRunner Runner2 = Mock<IBuildRunner>();

        protected static IBuildRunner SelectedRunner;

        Establish context = () =>
        {
            Runner1.Expect(r => r.RunnerName).Return("X");
            Runner2.Expect(r => r.RunnerName).Return("Y");
            
            Subject = new RunnerSelector(new[] {Runner1, Runner2});
        };
    }
}